import { Component, Host, h, Prop, Watch, Event, EventEmitter, State, ComponentInterface } from '@stencil/core';

/**
 * 文件选择
 *
 * @author chitanda
 * @date 2022-06-17 10:06:01
 * @export
 * @class IBzFileSelect
 */
@Component({
  tag: 'ibz-file-select',
  styleUrl: 'ibz-file-select.scss',
})
export class IBzFileSelect implements ComponentInterface {
  input: HTMLInputElement;

  /**
   * 文件内容
   *
   * @author chitanda
   * @date 2022-06-17 10:06:07
   * @type {string}
   */
  @Prop()
  value: string = '';
  @Watch('value')
  watchValue(): void {
    this.data = this.value;
  }

  /**
   * 文件内容
   *
   * @author chitanda
   * @date 2022-06-17 10:06:06
   * @type {string}
   */
  @State()
  data: string = '';

  /**
   * 限制文件上传类型
   *
   * @author chitanda
   * @date 2022-06-17 10:06:28
   * @type {string}
   */
  @Prop()
  accept: string = '';

  /**
   * 限制文件上传大小
   *
   * @description 单位：kb
   * @author chitanda
   * @date 2022-06-17 11:06:46
   * @type {number}
   */
  @Prop()
  size: number = 10240;

  /**
   * 是否禁用
   *
   * @author chitanda
   * @date 2022-06-17 19:06:06
   * @type {boolean}
   */
  @Prop()
  disabled: boolean = false;

  /**
   * 值变更
   *
   * @author chitanda
   * @date 2022-06-17 10:06:44
   * @type {EventEmitter<string>}
   */
  @Event({ eventName: 'value-change' })
  valueChangeEvt: EventEmitter<string>;

  /**
   * 文件名称
   *
   * @author chitanda
   * @date 2022-06-17 10:06:14
   * @type {string}
   */
  @Prop()
  fileName: string = '';
  @State()
  _fileName: string = '';
  @Watch('fileName')
  watchFileName(): void {
    this._fileName = this.fileName;
  }

  /**
   * 文件名称变更
   *
   * @author chitanda
   * @date 2022-06-17 14:06:26
   * @type {EventEmitter<string>}
   */
  @Event({ eventName: 'file-name-change' })
  fileNameChangeEvt: EventEmitter<string>;

  /**
   * 选中文件后缀
   *
   * @author chitanda
   * @date 2022-06-17 11:06:16
   * @readonly
   * @type {string}
   */
  get fileExtension(): string {
    if (this._fileName) {
      return this._fileName.split('.').pop();
    }
    return '';
  }

  /**
   * 选中文件 base64 前缀
   *
   * @author chitanda
   * @date 2022-06-17 11:06:11
   * @type {string}
   */
  get base64Type(): string {
    switch (this.fileExtension) {
      case 'txt':
        return 'data:text/plain;base64,';
      case 'doc':
        return 'data:application/msword;base64,';
      case 'docx':
        return 'data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,';
      case 'xls':
        return 'data:application/vnd.ms-excel;base64,';
      case 'xlsx':
        return 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,';
      case 'pdf':
        return 'data:application/pdf;base64,';
      case 'pptx':
        return 'data:application/vnd.openxmlformats-officedocument.presentationml.presentation;base64,';
      case 'ppt':
        return 'data:application/vnd.ms-powerpoint;base64,';
      case 'png':
        return 'data:image/png;base64,';
      case 'jpg':
        return 'data:image/jpeg;base64,';
      case 'gif':
        return 'data:image/gif;base64,';
      case 'svg':
        return 'data:image/svg+xml;base64,';
      case 'ico':
        return 'data:image/x-icon;base64,';
      case 'bmp':
        return 'data:image/bmp;base64,';
      default:
        return 'data:application/octet-stream;base64,';
    }
  }

  componentWillLoad(): void {
    this.data = this.value;
    this._fileName = this.fileName;
    console.log(this.data, this._fileName);
  }

  /**
   * 触发文件选择
   *
   * @author chitanda
   * @date 2022-06-17 10:06:38
   */
  openFileSelect() {
    this.input.click();
  }

  /**
   * 文件选择变更
   *
   * @author chitanda
   * @date 2022-06-17 10:06:59
   */
  async onChange(): Promise<void> {
    this.data = await this.readFileData();
    this.valueChangeEvt.emit(this.data);
    this.fileNameChangeEvt.emit(this._fileName);
  }

  /**
   * 读取文件内容
   *
   * @author chitanda
   * @date 2022-06-17 10:06:00
   * @return {*}  {(Promise<string>)}
   */
  readFileData(): Promise<string> {
    return new Promise(resolve => {
      const file = this.input.files[0];
      this._fileName = file.name;
      // 文件大小转换为 kb
      const size = file.size / 1024;
      if (size > this.size) {
        alert(`文件大小不能超过 ${this.size} kb`);
        return;
      }
      const reader = new FileReader();
      reader.onload = () => {
        let result: string;
        if (reader.result instanceof ArrayBuffer) {
          result = reader.result.toString();
        } else {
          result = reader.result;
        }
        result = result.substring(result.indexOf(';base64,') + 8);
        resolve(result);
      };
      reader.readAsDataURL(file);
    });
  }

  renderIcon() {
    return (
      <svg class='icon' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' width='12' height='12'>
        <path d='M574.55 522.35L904.4 192.5c16.65-16.65 16.65-44.1 0-60.75l-1.8-1.8c-16.65-16.65-44.1-16.65-60.75 0L512 460.25l-329.85-330.3c-16.65-16.65-44.1-16.65-60.75 0l-1.8 1.8c-17.1 16.65-17.1 44.1 0 60.75l329.85 329.85L119.6 852.2c-16.65 16.65-16.65 44.1 0 60.75l1.8 1.8c16.65 16.65 44.1 16.65 60.75 0L512 584.9l329.85 329.85c16.65 16.65 44.1 16.65 60.75 0l1.8-1.8c16.65-16.65 16.65-44.1 0-60.75L574.55 522.35z'></path>
      </svg>
    );
  }

  /**
   * 重置选择
   *
   * @author chitanda
   * @date 2022-06-17 14:06:05
   */
  resetSelect(): void {
    this.valueChangeEvt.emit('');
    this.fileNameChangeEvt.emit('');
  }

  render() {
    return (
      <Host class='ibz-file-select'>
        {this.data ? (
          <div class='select-file'>
            <div class='name'>
              <a title={this._fileName} href={`${this.base64Type}${this.data}`} download={this._fileName}>
                {this._fileName}
              </a>
            </div>
            <div class='action remove' onClick={() => this.resetSelect()}>
              {this.renderIcon()}
            </div>
          </div>
        ) : null}
        {!this.data ? (
          <div class='button button-tiny' onClick={() => this.openFileSelect()}>
            选择文件
          </div>
        ) : null}
        <input
          class='hidden-input'
          ref={ref => (this.input = ref)}
          type='file'
          accept={this.accept}
          value={this.data}
          onChange={() => this.onChange()}
        />
      </Host>
    );
  }
}
